#ifndef __TYPE_H__
#define __TYPE_H__
#include <iostream>
#include <string>
#include <vector>
#include "SymbolTable.h"
class Type {
   private:
    int kind;

   protected:
    enum { INT, VOID, FUNC, BOOL, STRING,PTR };
    int size;

   public:
    Type(int kind, int size = 0) : kind(kind), size(size){};
    ~Type(){};
    virtual std::string toStr() = 0;
    bool isInt() const { return kind == INT; };
    bool isVoid() const { return kind == VOID; };
    bool isFunc() const { return kind == FUNC; };
    bool isBool() const { return kind == BOOL; };
    bool isString() const { return kind == STRING; };
    int getKind() const { return kind;};
    int getSize() const { return size; };
};

class IntType : public Type {
   private:
    bool constant;

   public:
    IntType(int size, bool constant = false)
        : Type(Type::INT, size), constant(constant){};
    std::string toStr();
    bool isConst() const { return constant; };
};

class BoolType : public Type {
   public:
    BoolType(int size)
        : Type(Type::BOOL, size){};
    std::string toStr(){return "i1";};
};

class VoidType : public Type {
   public:
    VoidType() : Type(Type::VOID){};
    std::string toStr();
};

class FunctionType : public Type {
   private:
    Type* returnType;
    

   public:

    std::vector<Type*> paramsType;
    std::vector<SymbolEntry*> params_se;
    FunctionType(Type* returnType, std::vector<Type*> paramsType,std::vector<SymbolEntry*> paramsSym)
        : Type(Type::FUNC), returnType(returnType), paramsType(paramsType){this->params_se=paramsSym;};
    void setParamsType(std::vector<Type*> paramsType) {
        this->paramsType = paramsType;
    };
    std::string toStr();
    //增加返回rettype的函数，用于类型错误检测
    Type* getRetType() {return returnType;};
    std::vector<SymbolEntry*> getParamsSe() { return params_se; };
};

class PointerType : public Type
{
private:
    Type *valueType;
public:
    PointerType(Type* valueType) : Type(Type::PTR) {this->valueType = valueType;};
    Type* getPT(){return valueType;};
    std::string toStr();
};



class StringType : public Type {
   private:
    int length;

   public:
    StringType(int length) : Type(Type::STRING), length(length){};
    int getLength() const { return length; };
    std::string toStr();
};

class TypeSystem {
   private:
    static IntType commonInt;
    static VoidType commonVoid;
    static IntType commonConstInt;
    //增加布尔类型用来进行处理
    static BoolType commonBool;

   public:
    static Type* intType;
    static Type* voidType;
    static Type* constIntType;
    static Type *boolType;
};

#endif
